package com.zhp.utils;

import cn.hutool.core.util.ObjectUtil;
import cn.hutool.json.JSONUtil;
import com.zhp.enums.InitTypeEnums;

import java.lang.reflect.Field;

/**
 * @author zhanghp
 * @since 2024/5/31 16:59
 */
public class InitUtils {

    /**
     * 初始化指定类，并返回初始化对象
     *
     * @param cls 类
     * @return 对象
     * @param <T> 泛型
     */
    public static <T> T init(Class<T> cls){
        // 判断父类
        Class<? super T> superclass = cls.getSuperclass();
        Field[] declaredFields = superclass == null ? cls.getDeclaredFields() : copy(superclass.getDeclaredFields(), cls.getDeclaredFields());
        // 条件判断
        if (declaredFields == null || declaredFields.length == 0) {
            return null;
        }
        T t = null;
        try {
            t = cls.newInstance();
        } catch (InstantiationException e) {
            throw new RuntimeException("constructor init error, cls" + JSONUtil.toJsonStr(cls));
        } catch (IllegalAccessException e) {
            throw new RuntimeException("constructor is not accessible, cls:" + JSONUtil.toJsonStr(cls));
        }
        for (Field field : declaredFields) {
            field.setAccessible(Boolean.TRUE);
            try {
                if (ObjectUtil.isNotEmpty(field.get(t))) {
                    continue;
                }
                field.set(t, InitTypeEnums.getInit(field.getType()));
            } catch (IllegalAccessException e) {
                throw new RuntimeException("Field get or set Exception, Field" + JSONUtil.toJsonStr(field));
            }
        }
        return t;
    }

    /**
     * 给对象里的空字段，进行初始化
     *
     * @param cls 类
     * @param t 对象
     * @return 对象
     * @param <T> 泛型
     */
    public static <T> T init(Class<T> cls, T t){
        // 判断父类
        Class<? super T> superclass = cls.getSuperclass();
        Field[] declaredFields = superclass == null ? cls.getDeclaredFields() : copy(superclass.getDeclaredFields(), cls.getDeclaredFields());
        // 条件判断
        if (declaredFields == null || declaredFields.length == 0) {
            return t;
        }
        for (Field field : declaredFields) {
            field.setAccessible(Boolean.TRUE);
            try {
                if (ObjectUtil.isNotEmpty(field.get(t))) {
                    continue;
                }
                field.set(t, InitTypeEnums.getInit(field.getType()));
            } catch (IllegalAccessException e) {
                throw new RuntimeException("Field get or set Exception, Field" + JSONUtil.toJsonStr(field));
            }
        }
        return t;
    }

    /**
     * 子类和父类字段进行拷贝并生成一个新字段数组
     *
     * @param subClass 子类字段
     * @param superClass 父类字段
     * @return 字段数组
     */
    public static Field[] copy(Field[] subClass, Field[] superClass){
        if (subClass == null && superClass== null) {
            return null;
        }
        if (subClass == null || subClass.length == 0) {
            return superClass;
        }
        if (superClass == null || superClass.length == 0) {
            return subClass;
        }
        Field[] result = new Field[subClass.length + superClass.length];
        int index = 0;
        for (int i = 0; i < subClass.length; i++) {
            result[index ++] = subClass[i];
        }
        for (int i = 0; i < superClass.length; i++) {
            result[index ++] = superClass[i];
        }
        return result;
    }

}
